package dxn.nl.export.deal.netty;

import dxn.boot.common.config.CsApplicationContext;
import dxn.nl.export.deal.TopicDto;
import dxn.nl.export.deal.consumer.ThreadManager;
import dxn.nl.export.deal.export.ExportSessionManager;
import dxn.nl.file.biz.po.AppModelPo;
import dxn.nl.file.biz.service.AppModelBaseService;
import dxn.nl.file.biz.service.ConsumerBaseService;
import dxn.nl.file.biz.service.ExportFileBaseService;
import dxn.nl.file.biz.service.ImportFileBaseService;
import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Component
public class ExportDealBoot implements CommandLineRunner, DisposableBean, ApplicationListener<ContextClosedEvent> {
    private static final Logger log = LoggerFactory.getLogger(ExportDealBoot.class);
    //创建成员变量以便方法获取
    @Value("${cms.export.server.deal.appName:cms-export-deal}")
    private String applicationName;

    @Value("${cms.export.server.host}")
    private String serverHost;

    @Resource
    private AppModelBaseService appModelBaseService;

    @Resource
    private ExportFileBaseService exportFileBaseService;

    @Resource
    private ImportFileBaseService importFileBaseService;

    @Resource
    public ConsumerBaseService consumerBaseService;

    public static ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);

    public void run(String... args) {
        ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext)CsApplicationContext.getApplicationContext();
        try {

            log.info("启动导出处理客户端任务---------");
            if(serverHost == null || serverHost.equals(""))
            {
                // 通知应用程序退出
                applicationContext.close();
            }

            String[] hosts = serverHost.split(",");
            for(String host:hosts)
            {
                String[] ipPort = host.split(":");
                if(ipPort.length != 2)
                {
                    log.error(host+"服务地址不正确---------");
                    applicationContext.close();
                }
                int port = Integer.parseInt(ipPort[1]);
                ExportDealServer dealServer = new ExportDealServer(applicationName,ipPort[0],port);
                SocketManager.dealServerHashMap.add(dealServer);
            }

            for(ExportDealServer entry:SocketManager.dealServerHashMap)
            {
                boolean runResult = entry.run();
                if(!runResult)
                {
                    log.error(entry.getServerUrl()+"服务链接失败---------");
                }
            }

            log.debug("start...");
            // 在1s后执行任务 之后每2s执行一次任务
            pool.scheduleAtFixedRate(() -> {
                try {
                    for(ExportDealServer entry:SocketManager.dealServerHashMap)
                    {
                        entry.connect();
                    }
                } catch (Exception e) {
                    log.error("连接失败",e);
                }
            }, 5, 5, TimeUnit.SECONDS);

            init();

            // 在1s后执行任务 之后每2s执行一次任务
            pool.scheduleWithFixedDelay(() -> {
                try {
                    ThreadManager.selectAndPush();
                } catch (Exception e) {
                    log.error("连接失败",e);
                }
            }, 30, 5, TimeUnit.SECONDS);
        }
        catch (Exception ex)
        {
            log.error("链接失败",ex);
            applicationContext.close();
        }
    }

    @Override
    public void onApplicationEvent(@NotNull ContextClosedEvent contextClosedEvent) {
        try {
            log.info("开始停止导出任务");
            endJob();
        }
        catch (Exception ex)
        {
            log.error("",ex);
        }
    }

    @Override
    public void destroy() {
    }

    private void endJob()
    {
        try {
            if(!pool.isShutdown())
            {
                pool.shutdownNow();
                log.info("导出任务检查连接状态job终止");
            }
        }
        catch (Exception ex)
        {
            log.error("导出任务注销",ex);
        }

        try {
            for(ExportDealServer entry:SocketManager.dealServerHashMap)
            {
                entry.destroy();
            }
        }
        catch (Exception ex)
        {
            log.error("导出任务注销异常",ex);
        }

        try {
            Iterator<Map.Entry<String, ThreadPoolExecutor>> iterator = ThreadManager.topicThreadPoolMap.entrySet().iterator();
            while (iterator.hasNext()) {
                try {
                    iterator.next().getValue().shutdownNow();
                }
                catch (Exception exception)
                {

                }
            }
        }
        catch (Exception ex)
        {
            log.error("导出任务注销异常",ex);
        }

        try {
            ExportSessionManager.finishAllExportUtil("程序退出");
        }
        catch (Exception ex)
        {
            log.error("导出任务注销异常",ex);
        }

        //ExportSessionManager.addExportUtil(csNioMessage.getConfig().getSessionId(),pageQueryBiz);
    }

    private void init()
    {
        ThreadManager.exportFileBaseService = exportFileBaseService;
        ThreadManager.importFileBaseService = importFileBaseService;
        ThreadManager.consumerBaseService = consumerBaseService;

        List<AppModelPo> appModelPoList = appModelBaseService.list();
        ThreadManager.initThreadPool(appModelPoList);
    }
}
